package de.sas.za_gui.shell;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;

public class GameShell extends Shell
{
	static Display display;
	StackLayout stackLayout;
	Composite gameComposite;
	Composite configComposite;

	Spinner spinnerSizeCells;
	Spinner spinnerPopDuration;
	Spinner spinnerPercentPopulation;
	Button[] chkBtnsGetAlive = new Button[9];
	Button[] chkBtnsStayAlive = new Button[9];

	Runnable timer;
	static int popDuration = 150;
	static int size = 4;
	static double startPopulation;
	List<Integer> allowedToGetAlive = new ArrayList<Integer>();
	List<Integer> allowedToStayAlive = new ArrayList<Integer>();

	GameHandler handler;

	/**
	 * Launch the application.
	 * 
	 * @param args
	 */
	public static void main(String args[])
	{
		try
		{
			display = Display.getDefault();
			GameShell shell = new GameShell(display);
			shell.open();
			shell.layout();
			while (!shell.isDisposed())
			{
				if (!display.readAndDispatch())
				{
					display.sleep();
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Create the shell.
	 * 
	 * @param display
	 */
	public GameShell(final Display display)
	{
		super(display, SWT.SHELL_TRIM);
		stackLayout = new StackLayout();
		setLayout(stackLayout);

		configComposite = new Composite(this, SWT.NONE);

		Button chkBtnGetAlive_1 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_1.setBounds(60, 107, 27, 16);
		chkBtnGetAlive_1.setText("1");
		chkBtnsGetAlive[1] = chkBtnGetAlive_1;

		Button chkBtnGetAlive_2 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_2.setText("2");
		chkBtnGetAlive_2.setBounds(93, 107, 27, 16);
		chkBtnsGetAlive[2] = chkBtnGetAlive_2;

		Button chkBtnGetAlive_3 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_3.setSelection(true);
		chkBtnGetAlive_3.setText("3");
		chkBtnGetAlive_3.setBounds(126, 107, 27, 16);
		chkBtnsGetAlive[3] = chkBtnGetAlive_3;

		Button chkBtnGetAlive_4 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_4.setText("4");
		chkBtnGetAlive_4.setBounds(159, 107, 27, 16);
		chkBtnsGetAlive[4] = chkBtnGetAlive_4;

		Button chkBtnGetAlive_5 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_5.setText("5");
		chkBtnGetAlive_5.setBounds(192, 107, 27, 16);
		chkBtnsGetAlive[5] = chkBtnGetAlive_5;

		Button chkBtnGetAlive_6 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_6.setText("6");
		chkBtnGetAlive_6.setBounds(225, 107, 27, 16);
		chkBtnsGetAlive[6] = chkBtnGetAlive_6;

		Button chkBtnGetAlive_7 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_7.setText("7");
		chkBtnGetAlive_7.setBounds(258, 107, 27, 16);
		chkBtnsGetAlive[7] = chkBtnGetAlive_7;

		Button chkBtnGetAlive_8 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_8.setText("8");
		chkBtnGetAlive_8.setBounds(291, 107, 27, 16);
		chkBtnsGetAlive[8] = chkBtnGetAlive_8;

		Button chkBtnGetAlive_0 = new Button(configComposite, SWT.CHECK);
		chkBtnGetAlive_0.setText("0");
		chkBtnGetAlive_0.setBounds(27, 107, 27, 16);
		chkBtnsGetAlive[0] = chkBtnGetAlive_0;

		Button chkBtnStayAlive_1 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_1.setText("1");
		chkBtnStayAlive_1.setBounds(60, 148, 27, 16);
		chkBtnsStayAlive[1] = chkBtnStayAlive_1;

		Button chkBtnStayAlive_2 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_2.setSelection(true);
		chkBtnStayAlive_2.setText("2");
		chkBtnStayAlive_2.setBounds(93, 148, 27, 16);
		chkBtnsStayAlive[2] = chkBtnStayAlive_2;

		Button chkBtnStayAlive_3 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_3.setSelection(true);
		chkBtnStayAlive_3.setText("3");
		chkBtnStayAlive_3.setBounds(126, 148, 27, 16);
		chkBtnsStayAlive[3] = chkBtnStayAlive_3;

		Button chkBtnStayAlive_4 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_4.setText("4");
		chkBtnStayAlive_4.setBounds(159, 148, 27, 16);
		chkBtnsStayAlive[4] = chkBtnStayAlive_4;

		Button chkBtnStayAlive_5 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_5.setText("5");
		chkBtnStayAlive_5.setBounds(192, 148, 27, 16);
		chkBtnsStayAlive[5] = chkBtnStayAlive_5;

		Button chkBtnStayAlive_6 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_6.setText("6");
		chkBtnStayAlive_6.setBounds(225, 148, 27, 16);
		chkBtnsStayAlive[6] = chkBtnStayAlive_6;

		Button chkBtnStayAlive_7 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_7.setText("7");
		chkBtnStayAlive_7.setBounds(258, 148, 27, 16);
		chkBtnsStayAlive[7] = chkBtnStayAlive_7;

		Button chkBtnStayAlive_8 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_8.setText("8");
		chkBtnStayAlive_8.setBounds(291, 148, 27, 16);
		chkBtnsStayAlive[8] = chkBtnStayAlive_8;

		Button chkBtnStayAlive_0 = new Button(configComposite, SWT.CHECK);
		chkBtnStayAlive_0.setText("0");
		chkBtnStayAlive_0.setBounds(27, 148, 27, 16);
		chkBtnsStayAlive[0] = chkBtnStayAlive_0;

		Label lblAnzahlNachbarzellenBei = new Label(configComposite, SWT.NONE);
		lblAnzahlNachbarzellenBei.setBounds(27, 88, 324, 13);
		lblAnzahlNachbarzellenBei.setText("Anzahl Nachbarzellen, bei denen Zelle lebendig wird");

		Label lblAnzahlNachbarzellenBei_1 = new Label(configComposite, SWT.NONE);
		lblAnzahlNachbarzellenBei_1.setText("Anzahl Nachbarzellen, bei denen Zelle lebendig bleibt");
		lblAnzahlNachbarzellenBei_1.setBounds(27, 129, 324, 13);

		spinnerSizeCells = new Spinner(configComposite, SWT.BORDER);
		spinnerSizeCells.setMaximum(10);
		spinnerSizeCells.setMinimum(1);
		spinnerSizeCells.setSelection(4);
		spinnerSizeCells.setBounds(27, 62, 46, 20);

		Label lblGreDerZellen = new Label(configComposite, SWT.NONE);
		lblGreDerZellen.setBounds(24, 43, 92, 13);
		lblGreDerZellen.setText("Gr\u00F6\u00DFe der Zellen");

		Button btnOk = new Button(configComposite, SWT.NONE);
		btnOk.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseUp(MouseEvent e)
			{
				for (int i = 0; i < chkBtnsGetAlive.length; i++)
				{
					if (chkBtnsGetAlive[i].getSelection())
					{
						allowedToGetAlive.add(i);
					}
					if (chkBtnsStayAlive[i].getSelection())
					{
						allowedToStayAlive.add(i);
					}
				}
				startPopulation = spinnerPercentPopulation.getSelection() / 100.;
				size = spinnerSizeCells.getSelection();
				popDuration = spinnerPopDuration.getSelection();
				startComputing();
			}
		});
		btnOk.setBounds(27, 228, 68, 23);
		btnOk.setText("OK");

		spinnerPopDuration = new Spinner(configComposite, SWT.BORDER);
		spinnerPopDuration.setIncrement(25);
		spinnerPopDuration.setPageIncrement(25);
		spinnerPopDuration.setMaximum(2500);
		spinnerPopDuration.setMinimum(100);
		spinnerPopDuration.setSelection(150);
		spinnerPopDuration.setBounds(27, 202, 46, 20);

		Label lblZeitInMs = new Label(configComposite, SWT.NONE);
		lblZeitInMs.setText("Zeit in ms, nach denen neuer Zyklus berechnet wird");
		lblZeitInMs.setBounds(24, 183, 327, 13);

		createContents();
		stackLayout.topControl = configComposite;

		spinnerPercentPopulation = new Spinner(configComposite, SWT.BORDER);
		spinnerPercentPopulation.setSelection(31);
		spinnerPercentPopulation.setBounds(140, 62, 46, 20);

		Label lblProzentAnfangspopulation = new Label(configComposite, SWT.NONE);
		lblProzentAnfangspopulation.setBounds(137, 43, 181, 13);
		lblProzentAnfangspopulation.setText("Prozent Anfangspopulation");
		
		Menu menu = new Menu(this, SWT.BAR);
		setMenuBar(menu);
		
		MenuItem mntmNewSubmenu = new MenuItem(menu, SWT.CASCADE);
		mntmNewSubmenu.setText("Datei");
		
		Menu menu_1 = new Menu(mntmNewSubmenu);
		mntmNewSubmenu.setMenu(menu_1);
		
		MenuItem mntmNeu = new MenuItem(menu_1, SWT.NONE);
		mntmNeu.setText("Neu");
		
		MenuItem mntmDatei = new MenuItem(menu, SWT.NONE);
		mntmDatei.setText("Start");
		
		MenuItem mntmStop = new MenuItem(menu, SWT.NONE);
		mntmStop.setText("Pause");
		
		MenuItem mntmStep = new MenuItem(menu, SWT.NONE);
		mntmStep.setText("Step");

	}

	private void startComputing()
	{
		configComposite.dispose();

		gameComposite = new Composite(this, SWT.NONE);
		gameComposite.addPaintListener(new PaintListener()
		{
			public void paintControl(PaintEvent evt)
			{
				paintPopulation(evt);
			}
		});
		gameComposite.setLayout(new FillLayout(SWT.HORIZONTAL));

		timer = new Runnable()
		{
			@Override
			public void run()
			{
				gameComposite.redraw();
				handler.nextStep();
				getDisplay().timerExec(popDuration, this);
			}
		};
		stackLayout.topControl = gameComposite;
		this.layout();

		Point p = gameComposite.getSize();
		handler = new GameHandler(p.x / size, p.y / size, startPopulation, allowedToGetAlive, allowedToStayAlive);
		display.timerExec(popDuration, timer);
	}

	/**
	 * Create contents of the shell.
	 */
	protected void createContents()
	{
		setText("Game of Life");
		setSize(508, 527);

	}

	@Override
	protected void checkSubclass()
	{
		// Disable the check that prevents subclassing of SWT components
	}

	private void paintPopulation(PaintEvent evt)
	{
		Cell[][] field = handler.getField();

		Image image = new Image(getDisplay(), gameComposite.getSize().x, gameComposite.getSize().y);
		GC gc = new GC(image);
		gc.setBackground(new Color(getDisplay(), new RGB(0, 0, 0)));
		for (int x = 0; x < field.length; x++)
		{
			for (int y = 0; y < field[0].length; y++)
			{
				if (field[x][y].isAlive())
				{
					gc.fillRectangle(x * size, y * size, size, size);
				}
			}
		}
		evt.gc.drawImage(image, 0, 0);
		gc.dispose();
		image.dispose();
	}
}
